package com.fudan.adse.service.impl;

import com.fudan.adse.domain.po.Location;
import com.fudan.adse.domain.po.LocationExample;
import com.fudan.adse.domain.vo.LevelLocationVO;
import com.fudan.adse.mbg.mapper.LocationMapper;
import com.fudan.adse.service.LocationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class LocationServiceImpl implements LocationService {
    @Autowired
    private LocationMapper locationMapper;

    @Override
    public List<LevelLocationVO> getAllLocationsByCondition(String province, String city, String town) {
        LocationExample example = new LocationExample();
        LocationExample.Criteria criteria = example.createCriteria();
        if (province != null && !province.isEmpty()) {
            criteria.andProvinceLike("%" + province + "%");
        }
        if (city != null && !city.isEmpty()) {
            criteria.andCityLike("%" + city + "%");
        }
        if (town != null && !town.isEmpty()) {
            criteria.andTownLike("%" + town + "%");
        }
        List<Location> locations = locationMapper.selectByExample(example);
        locations.sort(Comparator.comparing(Location::getId));
        return buildLevelLocations(locations);

    }

    private List<LevelLocationVO> buildLevelLocations(List<Location> locations) {
        List<LevelLocationVO> ret = new ArrayList<>();
        Map<String, List<Location>> provinceMap = locations.stream().collect(Collectors.groupingBy(Location::getProvince));
        for (Map.Entry<String, List<Location>> entry : provinceMap.entrySet()) {
            entry.getValue().sort(Comparator.comparing(Location::getId));
            LevelLocationVO province = LevelLocationVO.builder()
                    .value(entry.getValue().isEmpty() ? 0 : entry.getValue().get(0).getId())
                    .label(entry.getKey())
                    .build();
            List<Location> cityList = entry.getValue().stream().filter(location -> location.getCity() != null && !location.getCity().isEmpty())
                    .collect(Collectors.toList());
            Map<String, List<Location>> cityMap = cityList.stream().collect(Collectors.groupingBy(Location::getCity));
            List<LevelLocationVO> cities = new ArrayList<>();
            cityMap.forEach((key, value) -> {
                value.sort(Comparator.comparing(Location::getId));
                LevelLocationVO city = LevelLocationVO.builder()
                        .value(value.isEmpty() ? 0 : value.get(0).getId())
                        .label(key).build();
                buildSubLevelLocations(city, value);
                cities.add(city);
            });
            province.setChildren(cities);
            ret.add(province);
        }
        return ret;
    }

    private void buildSubLevelLocations(LevelLocationVO locationVO, List<Location> townList) {
        List<LevelLocationVO> towns = new ArrayList<>();
        townList.forEach(location -> {
            if (location.getTown() != null && !location.getTown().trim().isEmpty()) {
                towns.add(LevelLocationVO.builder()
                        .value(location.getId())
                        .code(location.getCode())
                        .label(location.getTown())
                        .build());
            }
        });
        locationVO.setChildren(towns);
    }
}

